/**
 *	HoverScroll jQuery Plugin
 *
 *	Create a list which is scrollable by hovering the mouse over it
 *
 *	@author RasCarlito <carl.ogren@gmail.com>
 *	@version 0.1.0
 */
 
(function($) {

/**
 *	@method hoverscroll
 *	@param	params {Object}  Parameter list
 *		params = {
 *			vertical {Boolean},	// Vertical list or not ?
 *			width {Integer},	// Width of list container
 *			height {Integer},	// Height of list container
 *			debug {Boolean}		// Debug output in firebug console
 *		};
 */
$.fn.hoverscroll = function(params) {
	if (!params) { params = {}; }
	
	// Extend default
	params = $.extend({
		vertical:	false,
		width:		400,
		height:		50,
		debug:		false
	}, params);
	
	this.each(function() {
		var $this = $(this);
		
		if (params.debug) {
			$.log('[HoverScroll] Trying to create hoverscroll on element ' + this.tagName + '#' + this.id);
		}
		
		// wrap list with a container
		$this.wrap('<div class="ui-widget-content hoverscroll"></div>');
		
		$this.addClass('list').addClass('ui-helper-clearfix');
		
		// store handle to container
		var ctnr = $this.parent();
		
		if (params.debug) {
			if (ctnr.hasClass('hoverscroll')) { $.log('[HoverScroll] Wrapper created successfully'); }
			else { $.log('[HoverScroll] Could not create or select wrapper'); }
		}
		
		ctnr.width(params.width).height(params.height);
		
		var size = 0;
		
		// determine content width or height
		if (!params.vertical) {
			$this.children().each(function() {
				size += $(this).addClass('horizontal-item').outerWidth(true);
			});
			
			$this.width(size);
			size = ctnr.width();
		}
		else {
			$this.children().each(function() {
				size += $(this).addClass('vertical-item').outerHeight(true);
			});
			
			$this.height(size);
			size = ctnr.height();
		}
		
		// Define hover zones on container
		var zone = {
			1: { action: 'move', from: 0, to: 0.06 * size, direction: -1 , speed: 16 },
			2: { action: 'move', from: 0.06 * size, to: 0.15 * size, direction: -1 , speed: 8 },
			3: { action: 'move', from: 0.15 * size, to: 0.25 * size, direction: -1 , speed: 4 },
			4: { action: 'move', from: 0.25 * size, to: 0.4 * size, direction: -1 , speed: 2 },
			5: { action: 'stop', from: 0.4 * size, to: 0.6 * size },
			6: { action: 'move', from: 0.6 * size, to: 0.75 * size, direction: 1 , speed: 2 },
			7: { action: 'move', from: 0.75 * size, to: 0.85 * size, direction: 1 , speed: 4 },
			8: { action: 'move', from: 0.85 * size, to: 0.94 * size, direction: 1 , speed: 8 },
			9: { action: 'move', from: 0.94 * size, to: size, direction: 1 , speed: 16 }
		}
		
		
		// Set default state values to container
		ctnr[0].isChanging = false;
		ctnr[0].direction  = 0;
		ctnr[0].speed      = 1;
		
		
		/**
		 *	Check mouse position relative to hoverscroll container
		 *	and trigger actions according to the zone table
		 *
		 *	@param x {Integer} Mouse X event position
		 *	@param y {Integer} Mouse Y event position
		 */
		function checkMouse(x, y) {
			x = x - ctnr.offset().left;
			y = y - ctnr.offset().top;
			
			var pos;
			if (!params.vertical) { pos = x; }
			else { pos = y; }
			
			for (i in zone) {
				if (pos >= zone[i].from && pos < zone[i].to) {
					if (zone[i].action == 'move') {
						startMoving(zone[i].direction, zone[i].speed);
					}
					else {
						stopMoving();
					}
				}
			}
		}
		
		/**
		 *	Start scrolling the list with a given speed and direction
		 *
		 *	@param direction {Integer}	Direction of the displacement, either -1|1
		 *	@param speed {Integer}		Speed of the displacement (20 being very fast)
		 */
		function startMoving(direction, speed) {
			if (ctnr[0].direction != direction) {
				stopMoving();
				ctnr[0].direction  = direction;
				ctnr[0].isChanging = true;
				move();
			}
			ctnr[0].speed = speed;
		}
		
		/**
		 *	Stop scrolling the list
		 */
		function stopMoving() {
			ctnr[0].isChanging = false;
			ctnr[0].direction  = 0;
			ctnr[0].speed      = 1;
			clearTimeout(ctnr[0].timer);
		}
		
		/**
		 *	Move the list one step in the given direction and speed
		 */
		function move() {
			if (ctnr[0].isChanging == false) { return; }
			
			var scrollSide;
			if (!params.vertical) { scrollSide = 'scrollLeft'; }
			else { scrollSide = 'scrollTop'; }
			
			ctnr[0][scrollSide] += ctnr[0].direction * ctnr[0].speed;
			ctnr[0].timer = setTimeout(function() { move(); }, 50);
		}
		
		// Bind actions to the hoverscroll container
		ctnr
		// Bind checkMouse to the onmousemove
		.mousemove(function(e) { checkMouse(e.pageX, e.pageY); })
		// Bind stopMoving to the onmouseout
		.mouseleave(function() { stopMoving(); });
	});
	
	return this;
};


/**
 *	log to firebug console if exists
 */
$.log = function(msg) {
	if (console && console.log) {
		console.log(msg);
	}
};


})(jQuery);
